programming4us
           
 
 
Programming

DirectX 10 Game Programming : The 2D Resurgence - Sprites

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
9/10/2011 4:39:48 PM
2D games just wouldn’t be the same without sprites. Before you start thinking soda or fairies, sprites are 2D graphical representations of characters or objects within a game. Every tree, treasure chest, or dungeon creature you encounter is presented on-screen using a sprite. Sprites are one of the most widely used and easily understood aspects of 2D game programming. Figure 1 shows an example of a sprite created from a colored rectangle.
Figure 1. An example of a sprite.


Sprites come in all different sizes, but tend to come in only one shape, rectangular. Because of their shape, sprites need only a width and height to define their area and are more easily controlled from a programmer’s perspective. Since your game is taking place in a 2D area consisting of only width and height, it only takes two variables to describe the sprite’s location. These two variables are commonly referred to as X and Y. The X variable controls the horizontal position with Y controlling the vertical.

Moving a character sprite along a straight line from one side of the screen to the other is simple. The sprite’s location need only change horizontally, without any concern for depth. Because of the lack of actual depth in sprite-based games, depth is normally faked by a technique called Z ordering.

Z Ordering

Z ordering is the process in which objects are sorted before being drawn. Each sprite you create can be given a different Z-order value designating the depth at which it should be drawn. Sprites with a lower Z-order value are drawn behind those sprites with a higher value, giving the illusion of depth. Figure 2 shows how Z ordering works.

Figure 2. A diagram demonstrating Z ordering.


Sprite Image

The most important aspect of a sprite is its image. Each sprite needs an image to be associated with it both from a gameplay perspective and a technical one. The image is what the sprite uses to convey its purpose to the player. For instance, your main character sprite in an RPG game may be the image of a knight or even a spaceship in a space battle. You can choose any image you’d like, but your sprite can’t be displayed without an image.

Earlier you learned how to load a texture from the disk; now you’ll learn how textures can be used with sprites.

Shader Resource Views

Before a texture can be attached to a sprite, it needs to be configured into a format the sprite can use. The way resources are accessed in Direct3D differs based on how the resource is going to be used. Resources, such as textures, are commonly stored linearly in a buffer within memory. While this is an easy way to load the texture, it isn’t always in the format that is most efficient for the video hardware. Direct3D solves this problem by using resource views.

A resource view allows data to be accessed differently based on part of the Direct3D pipeline using it. When creating a sprite, the D3DX10_SPRITE structure expects the texturetobeaccessedthroughan ID3D10ShaderResourceView object, which helps the shader know how to use a particular resource.

The ID3D10ShaderResourceView is created using the CreateShaderResourceView function.

The CreateShaderResourceView function takes three parameters.

The first parameter is a pointer to the texture resource from which to create the view. The second parameter is a pointer to a D3D10_SHADER_RESOURCE_VIEW_DESC structure. This structure is used to define the type of resource view being created. The final parameter is the newly created ID3D10ShaderResourceView.

Before the shader resource view can be created, you need to create and fill out the D3D10_SHADER_RESOURCE_VIEW_DESC structure.

typedef struct D3D10_SHADER_RESOURCE_VIEW_DESC {
DXGI_FORMAT Format;
D3D10_SRV_DIMENSION ViewDimension;
union {
D3D10_BUFFER_SRV Buffer;
D3D10_TEX1D_SRV Texture1D;
D3D10_TEX1D_ARRAY_SRV Texture1DArray;
D3D10_TEX2D_SRV Texture2D;
D3D10_TEX2D_ARRAY_SRV Texture2DArray;
D3D10_TEX2DMS_SRV Texture2DMS;
D3D10_TEX2DMS_ARRAY_SRV Texture2DMSArray;
D3D10_TEX3D_SRV Texture3D;
D3D10_TEXCUBE_SRV TextureCube;
};
} D3D10_SHADER_RESOURCE_VIEW_DESC;

Although the size of the D3D10_SHADER_RESOURCE_VIEW_DESC structure may look imposing, there are only a few variables that need to be filled out.

The DXGI_FORMAT is simply the texture format. This information is available in the D3D10_TEXTURE2D_DESC structure by calling the GetDesc function.

The D3D10_SRV_DIMENSION lets the resource view know the type of texture it is representing. This will most commonly be a 2D texture.

The last piece is to fill out the variables that pertain to the type of texture resource. In the case of 2D textures, this includes information like the number of mip levels.

The following code sample shows how to create and complete the D3D10_SHADER_ RESOURCE_VIEW_DESC structure.

// Load the texture for the sprite
ID3D10Texture2D* texture = GetTexture2DFromFile(TEXT("../brick.bmp"));

// Make sure there's a valid texture
if (texture != NULL)
{
// Get the texture details
D3D10_TEXTURE2D_DESC desc;
texture->GetDesc( &desc );

// Create a shader resource view of the texture
D3D10_SHADER_RESOURCE_VIEW_DESC SRVDesc;
// Clear out the shader resource view description structure
ZeroMemory( &SRVDesc, sizeof(SRVDesc) );

// Set the texture format
SRVDesc.Format = desc.Format;
// Set the type of resource
SRVDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
SRVDesc.Texture2D.MipLevels = desc.MipLevels;
}

Once you have a completed D3D10_SHADER_RESOURCE_VIEW_DESC structure, you can call the CreateShaderResourceView function. The following code shows how to use this function to create a resource view.

ID3D10ShaderResourceView *gSpriteTextureRV = NULL;
pD3DDevice->CreateShaderResourceView(texture, &SRVDesc, &gSpriteTextureRV);

When the call is complete, the gSpriteTextureRV function will contain a valid shader resource view usable to create a sprite.

Creating a Sprite

Now that you have your image data ready, it’s time to create the sprite. Direct3D has built-in support for sprites so there won’t be a need to mess with the textures directly like you did in the first example.

There are a few easy steps you need to follow to create a sprite. First, define each of your sprites using a D3DX10_SPRITE structure. Second, use the ID3DX10Sprite interface to manipulate and draw the sprites. The steps are detailed in the following sections.

The D3DX10_SPRITE Structure

Direct3D has a special object reserved specifically for representing sprites: the D3DX10_SPRITE structure. This structure contains variables for specifying everything Direct3D needs to know in order to draw the sprite, including its position, texture, resource, and color. By filling in this structure, you’re detailing how and where you want your sprite drawn by Direct3D. Each sprite your game displays will need one of these structures filled out with the sprite’s appropriate data.

typedef struct D3DX10_SPRITE {
D3DXMATRIX matWorld;
D3DXVECTOR2 TexCoord;
D3DXVECTOR2 TexSize;
D3DXCOLOR ColorModulate;
ID3D10ShaderResourceView * pTexture;
UINT TextureIndex;
} D3DX10_SPRITE;

The first member of the D3DX10_SPRITE structure is the matWorld variable. This variable contains the transform used to specify where the sprite should be drawn.

The second member is TexCoord; this is the sprite’s texture coordinate. The texture coordinate describes the location of the sprite’s top-left corner in its image data. This value ranges from 0 to 1.

TexSize details the size of the texture used for the sprite. This value, ranging from 0 to 1, will tell the sprite just how much of the image data it uses.

The fourth member is ColorModulate. Whichever color is specified in this variable will be applied to the sprite before it’s drawn. If the sprite is being drawn at full brightness and color, this variable is normally white.

pTexture is a pointer to the shader resource view that represents the texture the sprite will use.

Lastly, TextureIndex is the index into an array of textures. If the texture being used for the sprite is not a texture array, this value should be 0.

The following small code sample shows how to create and initialize a sprite using the D3DX10_SPRITE structure.

// Create a new sprite variable
D3DX10_SPRITE testSprite;

// Set the sprite's shader resource view
testSprite.pTexture = gSpriteTextureRV;

// top-left location in U,V coords
testSprite.TexCoord.x = 0;
testSprite.TexCoord.y = 0;

// Determine the texture size in U,V coords
testSprite.TexSize.x = 1.0f;
testSprite.TexSize.y = 1.0f;

// Set the texture index. Single textures will use 0
testSprite.TextureIndex = 0;

// The color to apply to this sprite, full color applies white.
testSprite.ColorModulate = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);

The preceding code assumed that the sprite was using the entire contents of the image by specifying 0 for the texture coordinates and 1.0 for the texture size.

The Direct3D Sprite System

Direct3D includes an interface for managing and drawing the sprites defined in the D3DX10_SPRITE structures. This interface, ID3DX10Sprite, is the main workhorse of sprite drawing. The ID3DX10Sprite interface expects the application to create one or more sprite structures for it to manage. It takes the structures, sorts them, and sends them to the graphics hardware to be drawn.

You can create an ID3DX10Sprite object using the D3DX10CreateSprite function. The D3DX10CreateSprite function takes only three parameters.

The first parameter is a pointer to the D3DX10Device you created when Direct3D was initialized.

Second is the number of sprites to be rendered at any one time. Specifying 0 for this parameter will cause Direct3D to default to 4096.

The final parameter is a pointer to an ID3DX10Sprite interface waiting to be initialized.

The following code sample shows how to create and initialize the sprite system.

ID3DX10Sprite   *spriteObject = NULL;

// create the sprite object
HRESULT hr = D3DX10CreateSprite(pD3DDevice, 0, &spriteObject);

// Make sure the sprite creation was successful
if (hr != S_OK)
{
// Handle failure
}

Remember to release the ID3DX10Sprite interface after you’re done using it. Failure to do so will cause a memory leak.

// spriteObject contains a valid ID3DX10Sprite object
if (spriteObject)
{
spriteObject->Release();
spriteObject = NULL;
}

Getting the Sprite to the Screen

When drawing sprites, the sprite object needs to know a few things about the environment in which it’s drawing. Not only does it need to know the position of each and every sprite, but it needs to know the specifics about the area in which it’s drawing. This means the sprite object must be aware of the boundaries of the area where the sprites will be drawn. Normally, the size of this area is determined by the viewport associated with the Direct3D device. Figure 3 shows how a viewport is laid out.

Figure 3. Viewport example.


The area in which the sprites are drawn, in this case, will consist of the entire viewport. The SetProjectionTransform function is used to set the available drawing area for the sprite object. The SetProjectionTransform function takes one parameter, a D3DXMATRIX structure called the projection matrix, which defines the dimensions of the drawing area.

The function D3DXMatrixOrthoOffCenterLH is used to create the projection matrix. The first parameter for this function is a pointer to a D3DXMATRIX structure where the resulting projection matrix is placed. D3DXMatrixOrthoOffCenterLH creates a left-handed projection matrix that is used for setting up the viewport for sprite drawing. This function is used specifically to offset the coordinates used causing the top-left corner to be at 0, 0.

The second, third, fourth, and fifth parameters define the drawing area.

The last two parameters determine the depth of the scene. Even though sprites have no depth, the projection matrix needs valid depth values. The depth values are used by the system to figure out when to clip pieces of the scene.

The following code sample shows how to create a projection matrix based on the viewport.

The projection matrix
D3DXMATRIX matProjection;

// Create the projection matrix using the values in the viewport
D3DXMatrixOrthoOffCenterLH(&matProjection,
(float)viewPort.TopLeftX,
(float)viewPort.Width,
(float)viewPort.TopLeftY,
(float)viewPort.Height,
0.1f,
10);

// Set the projection matrix
HRESULT hr = spriteObject->SetProjectionTransform(&matProjection);

The projection matrix lets the system know the size of the grid on which the sprites will be placed. In the previous code sample, if the viewport is 640 pixels wide and 480 pixels tall, then the projection matrix would restrict visible sprite drawing to that area. Sprites positioned outside of this area would not be visible on the screen.

The projection matrix only needs to be changed if the size of the viewport changes.

Positioning and Scaling the Sprite

Now that the sprites know the extent of their environment, positioning them within it is possible. The act of moving an object within a space is called translation. Sprites being two dimensional in nature can be translated in two directions, X and Y. If you want to position a sprite in the center of a 640 × 480 display area, you would translate the sprite to an X, Y position of (320, 240). This in effect, moves the sprite 320 pixels horizontally and 240 pixels vertically. When sprites are translated, they’re moved based on an internal point called the translation point. The translation point on a sprite is by default in the sprite’s center. You can see an example of a sprite’s translation point in Figure 4.

Figure 4. A sprite’s translation point. This point defaults to the sprite’s center.


Because the default translation point for the sprite was in its center, the sprite appears correctly centered on the screen. When using sprites for characters within a game, it is common for the translation point to be moved to the top-left corner of the sprite.

When translating a sprite it is necessary to create another matrix called the translation matrix. The translation matrix, once defined, is used by Direct3D to position the sprite. The translation matrix can be created by using the function D3DXMatrix Translation. The D3DXMatrixTranslation function uses four parameters.

The first parameter is a pointer to the output translation matrix.

The second and third parameters are the X and Y position where the sprite should be moved.

The final parameter is the depth at which the sprite should be placed.

The following code sample shows how to use this function.

// these variables describe the dimensions of the sprite
// and where it should be located.
float spritePosX = 320;
float spritePosY = 240;
float spriteWidth = 64;
float spriteHeight = 64;

// The translation matrix to be created
D3DXMATRIX matTranslation;

// Create the translation matrix
D3DXMatrixTranslation( &matTranslation,
spritePosX,
(windowHeight - spritePosY),
0.1f);

When positioning a sprite vertically, it is necessary to subtract the destination Y position from the height of the application window. This allows the sprite to be positioned based on the top-left corner of the window. Figure 5 shows a diagram of a sprite centered in the viewport area.

Figure 5. A centered sprite.


By default, Direct3D will draw your sprites only 1 pixel tall and 1 pixel wide. To make sure your sprite gets drawn at its correct size, the sprite must be scaled. Scaling the sprite requires the use of one more matrix, the scaling matrix.

The scaling matrix is created using the D3DXMatrixScaling function.

The D3DXMatrixScaling function takes four parameters.

The first parameter is a pointer to the output scaling matrix. The second and third parameters are the values by which to scale the sprite in the X and Y directions, respectively. Passing in the sprite’s width and height values will make sure the sprite is sized correctly.

The final parameter is the amount to scale the sprite’s depth. Since the sprite shouldn’t be scaled in this direction, you should pass 1.0f as the default value.

The following code sample shows how to use the D3DXMatrixScaling function to create the scaling matrix.

// Scale the sprite to its correct width and height
D3DXMATRIX matScaling;
D3DXMatrixScaling(&matScaling, spriteWidth, spriteHeight, 1.0f );

So now that you have the translation matrix and the scaling matrix, what do you do with them? Do you remember the matWorld parameter of the D3DX10_SPRITE structure? This parameter is the world transform, which positions the sprite. The translation and scaling matrices need to be multiplied together to get the correct value for the matWorld parameter. This code snippet shows how this is accomplished.

// The sprite structure, the rest of the parameters should be filled in as well.
D3DX10_SPRITE testSprite;

// Setting the sprite's position and size
testSprite.matWorld = (matScaling * matTranslation);


You’ve come a long way so far; there’s only one more step, drawing.

Drawing the Sprite

The drawing of a sprite takes place within your render function. Previously, you had used the Render function to clear the render target. Now, you’re going to add the drawing of the sprite as well.

To draw the sprite, you need some functionality provided by the sprite object (ID3DX10Sprite). All drawing of sprites takes place between two calls, Begin and End. Seems simple enough. The Begin call prepares Direct3D to draw sprites, setting up the proper internal states. The End call finalizes the drawing. Table 1 shows the possible flags that can be sent to the Begin function.

Table 1. Sprite Flags
FlagDescription
D3DX10_SPRITE_SORT_TEXTURESort the sprites by texture.
D3DX10_SPRITE_SORT_DEPTH_BACK_TO_FRONTSort the sprites from back to front based on Z order.
D3DX10_SPRITE_SORT_DEPTH_FRONT_TO_BACKSort the sprites from front to back based on Z order.
D3DX10_SPRITE_SAVE_STATEMakes sure the render state before sprite drawing is restored when the End function is called.
D3DX10_SPRITE_ADDREF_TEXTURESCauses the reference count for each sprite texture to be incremented.

Tip

Sprites can be made to have transparent areas by giving their textures an alpha layer in your paint program and applying a Direct3D blend state.


The key function for sprite drawing is the DrawSpritesImmediate function. This is the function that takes the sprite and sends it to the video card to be drawn. The DrawSpritesImmediate function takes four parameters.

The first parameter is the sprite structure you created earlier, testSprite.

The second parameter is the number of sprites that DrawSpritesImmediate is expected to draw. In this example, only one sprite is needed.

The third parameter is the size of the D3DX10_SPRITE structure. Passing 0 will default to the proper size.

The final parameter is reserved and should be set to 0.

The DrawSpriteImmediate function has the capability of drawing more than one sprite. This functionality will be explained in the next section.

/*******************************************************************
* Render
* All drawing happens in the Render function
* Inputs - void
* Outputs - void
*******************************************************************/

void Render()
{
if (pD3DDevice != NULL)
{
// clear the target buffer
pD3DDevice->ClearRenderTargetView(pRenderTargetView, D3DXCOLOR (0.0f,
0.0f, 0.0f, 0.0f));

// start drawing the sprites
spriteObject->Begin(D3DX10_SPRITE_SORT_TEXTURE);

// Draw all the sprites
spriteObject->DrawSpritesImmediate(testSprite, 1, 0, 0);

// Finish up and send the sprites to the hardware
spriteObject->End();

// display the next item in the swap chain
pSwapChain->Present(0, 0);
}
}

Other -----------------
- DirectX 10 Game Programming : The 2D Resurgence - Textures
- Programming Excel with VBA and .NET : Tasks in Visual Basic - Run Other Applications
- Programming Excel with VBA and .NET : Tasks in Visual Basic - Find Truth & Compare Bits
- Programming WCF Services : Queued Services - Delivery Failures (part 2) - Processing the Dead-Letter Queue
- Programming WCF Services : Queued Services - Delivery Failures (part 1) - Configuring the Dead-Letter Queue
- Parallel Programming with Microsoft Visual Studio 2010 : Task Parallelism - Cancellation
- Parallel Programming with Microsoft Visual Studio 2010 : Task Parallelism - Sort Examples
- jQuery 1.3 : DOM Manipulation - Wrapping elements & Copying elements
- iOS SDK : Debugging (part 4) - Instruments—Leaks
- iOS SDK : Debugging (part 3) - NSZombieEnabled
- iOS SDK : Debugging (part 2) - Watchpoints
- iOS SDK : Debugging (part1 )
- iOS SDK : Installing Applications on an iPhone
- Software Testing with Visual Studio Team System 2008 : Web Testing - Recording a test
- Software Testing with Visual Studio Team System 2008 : Unit testing web services & Code coverage unit test
- .NET Debugging : Introduction to the Tools - SOS & SOSEX
- .NET Debugging : CLR 4.0 - Synchronization & Interoperability
- iPhone Programming : Connecting to the Network - Getting Data from the Internet
- iPhone Programming : Connecting to the Network - Sending Email
- Programming Excel with VBA and .NET : Tasks in Visual Basic - Check Results
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us